package common

import (
	"common/configx"
	"common/databasex"
	"common/sentryx"
	"common/zapx"
)

type Bootstrap struct {
	CallFunc []BootstrapCallFunInterface
}

type BootstrapCallFunInterface interface {
	Connect() error
	Shutdown() error
}

type BootstrapOpt func(bt *Bootstrap)

type BootstrapInitOpt func(config configx.Config) any

func WithBootstrapInit(fun func(config configx.Config) any) BootstrapInitOpt {
	return func(config configx.Config) any {
		return fun(config)
	}
}

// Init 初始化程序
func Init(configPath string, opts ...BootstrapInitOpt) error {
	//初始化配置
	if err := configx.Init(configPath); err != nil {
		return err
	}

	var zapxOpt []zapx.LoggerStructOpt
	var databasexOpt []databasex.ManageOpt

	for _, opt := range opts {
		o := opt(configx.C)
		switch v := o.(type) {
		case zapx.LoggerStructOpt:
			zapxOpt = append(zapxOpt, v)
			break
		case databasex.ManageOpt:
			databasexOpt = append(databasexOpt, v)
		}
	}

	//初始化sentry
	if err := sentryx.Init(); err != nil {
		return err
	}

	//初始化日志
	if err := zapx.Init(zapxOpt...); err != nil {
		return err
	}
	//初始化mysql
	if err := databasex.Init(databasexOpt...); err != nil {
		return err
	}
	return nil
}

// NewBootstrap 创建引导程序
func NewBootstrap(opts ...BootstrapOpt) *Bootstrap {
	bt := &Bootstrap{}
	for _, opt := range opts {
		opt(bt)
	}
	return bt
}

// WithBootstrapCallFunc 启动时调用
func WithBootstrapCallFunc(callFun BootstrapCallFunInterface) BootstrapOpt {
	return func(bt *Bootstrap) {
		bt.CallFunc = append(bt.CallFunc, callFun)
	}
}

// Boot 引导启动
func (bt *Bootstrap) Boot() error {
	for _, funInterface := range bt.CallFunc {
		if err := funInterface.Connect(); err != nil {
			return err
		}
	}
	return nil
}

// Shutdown 程序退出
func (bt *Bootstrap) Shutdown() {
	zapx.Logger.Sync()
	for _, funInterface := range bt.CallFunc {
		funInterface.Shutdown()
	}
}
